#include "main.h"
#include "led.h"
#include "delay.h"
#include "beep.h"
#include "usart1.h"
#include "oled.h"
#include "eeprom.h"
#include "w25qxx.h"
#include "printf.h"
#include "key.h"
#include "drv8833.h"
#include "rtc.h"
#include "can.h"
#include "esp32.h"

#define START_TASK_PRIO             1
#define START_STK_SIZE              512
OS_TCB Start_TCB = {0};
CPU_STK Start_STK[START_STK_SIZE];
void start_task(void* p_arg);

#define TASK1_TASK_PRIO             2
#define TASK1_STK_SIZE              512
OS_TCB Task1_TCB = { 0 };
CPU_STK Task1_STK[TASK1_STK_SIZE];
void task1_task(void* p_arg);

#define OLED_TASK_PRIO              3
#define OLED_STK_SIZE               128
OS_TCB OLED_TCB = { 0 };
CPU_STK OLED_STK[OLED_STK_SIZE];
void oled_task(void* p_arg);

#define KEY_TASK_PRIO               4
#define KEY_STK_SIZE            128
OS_TCB KEY_TCB = { 0 };
CPU_STK KEY_STK[KEY_STK_SIZE];
void key_task(void* p_arg);

#define BEEP_TASK_PRIO              5
#define BEEP_STK_SIZE               128
OS_TCB BEEP_TCB = { 0 };
CPU_STK BEEP_STK[BEEP_STK_SIZE];
void beep_task(void* p_arg);

#define USART2_TASK_PRIO            6
#define USART2_STK_SIZE             128
OS_TCB USART2_TCB = { 0 };
CPU_STK USART2_STK[USART2_STK_SIZE];
void usart2_task(void* p_arg);

#define CAN_TASK_PRIO               7
#define CAN_STK_SIZE            128
OS_TCB CAN_TCB = { 0 };
CPU_STK CAN_STK[CAN_STK_SIZE];
void can_task(void* p_arg);

int main()
{
    OS_ERR os_err;

    delay_init(72); //时钟配置

    OSInit(&os_err);
    if(os_err != OS_ERR_NONE) while(1);

    OSTaskCreate(&Start_TCB,
                 "start_task",
                 start_task,
                 NULL,
                 START_TASK_PRIO,
                 &Start_STK[0],
                 START_STK_SIZE / 10,
                 START_STK_SIZE,
                 0,
                 0,
                 NULL,
                 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR,
                 &os_err);

    if(os_err != OS_ERR_NONE) while(1);

    OSStart(&os_err);

    while(1);
}

void bsp_init(void)
{
    led_init();
    beep_init();
    key_init();
    drv8833_init();

    usart1_init(115200);
    can_init();
    esp32_init();

    u8g2_init();

    at24_init(); //eeprom init
    w25q_init();

    rtc_init();

}

//启动函数的任务函数
void start_task(void* p_arg)
{
    CPU_SR cpu_sr = 0;
    OS_ERR os_err = 0;

    bsp_init(); //完成其他硬件初始化

    //创建各种任务的
    CPU_CRITICAL_ENTER(); //进入临界状态

    OSTaskCreate(&Task1_TCB, //任务控制块，作为唯一性
                 "task1_task", //任务名称
                 task1_task, //任务函数
                 NULL, //传递给任务函数的参数
                 TASK1_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
                 &Task1_STK[0], //UCOSIII中，需要的是栈底
                 TASK1_STK_SIZE / 10, //设置栈空间大小的最小值
                 TASK1_STK_SIZE, //栈空间大小
                 0, //内部消息个数
                 0, //时间片轮训大小
                 NULL,
                 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
                 &os_err);

    // OSTaskCreate(&OLED_TCB, //任务控制块，作为唯一性
    // "oled_task", //任务名称
    // oled_task, //任务函数
    // NULL, //传递给任务函数的参数
    // OLED_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
    // &OLED_STK[0], //UCOSIII中，需要的是栈底
    // OLED_STK_SIZE / 10, //设置栈空间大小的最小值
    // OLED_STK_SIZE, //栈空间大小
    // 0, //内部消息个数
    // 0, //时间片轮训大小
    // NULL,
    // OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
    // &os_err);

    // OSTaskCreate(&KEY_TCB, //任务控制块，作为唯一性
    // "key_task", //任务名称
    // key_task, //任务函数
    // NULL, //传递给任务函数的参数
    // KEY_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
    // &KEY_STK[0], //UCOSIII中，需要的是栈底
    // KEY_STK_SIZE / 10, //设置栈空间大小的最小值
    // KEY_STK_SIZE, //栈空间大小
    // 0, //内部消息个数
    // 0, //时间片轮训大小
    // NULL,
    // OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
    // &os_err);

    OSTaskCreate(&BEEP_TCB, //任务控制块，作为唯一性
                 "beep_task", //任务名称
                 beep_task, //任务函数
                 NULL, //传递给任务函数的参数
                 BEEP_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
                 &BEEP_STK[0], //UCOSIII中，需要的是栈底
                 BEEP_STK_SIZE / 10, //设置栈空间大小的最小值
                 BEEP_STK_SIZE, //栈空间大小
                 0, //内部消息个数
                 0, //时间片轮训大小
                 NULL,
                 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
                 &os_err);

    // OSTaskCreate(&USART2_TCB, //任务控制块，作为唯一性
    // "usart2_task", //任务名称
    // usart2_task, //任务函数
    // NULL, //传递给任务函数的参数
    // USART2_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
    // &USART2_STK[0], //UCOSIII中，需要的是栈底
    // USART2_STK_SIZE / 10, //设置栈空间大小的最小值
    // USART2_STK_SIZE, //栈空间大小
    // 0, //内部消息个数
    // 0, //时间片轮训大小
    // NULL,
    // OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
    // &os_err);
    // OSTaskCreate(&CAN_TCB, //任务控制块，作为唯一性
    // "can_task", //任务名称
    // can_task, //任务函数
    // NULL, //传递给任务函数的参数
    // CAN_TASK_PRIO, //任务优先级，在UCOSIII是允许优先级重复的
    // &CAN_STK[0], //UCOSIII中，需要的是栈底
    // CAN_STK_SIZE / 10, //设置栈空间大小的最小值
    // CAN_STK_SIZE, //栈空间大小
    // 0, //内部消息个数
    // 0, //时间片轮训大小
    // NULL,
    // OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, //操作型参数
    // &os_err);

    CPU_CRITICAL_EXIT(); //退出

    uint8_t i = 0;
    char str[20] = {0};
    // beep_b(100);
    // delay_ms(20);

    while(1) {
        LED = !LED;
        delay_ms(500);

        printf("CAN TX=%03d", i);
        i++;

        // OLED_PrintStr(0, 16, str, Font16);
        // CAN1_Tx(0x00, &i, 1);
    }
}

uint8_t i = 0; //0-255

void task1_task(void* p_arg)
{
    OS_ERR os_err = 0;
    char str[20] = {0};
    uint8_t at24s = at24_check();
    uint32_t w25qId = W25QXX_ReadID();
    DateTime_t dateTime = {0};
    int8_t keyStatus = -1;
    while(1) {

        if(DRV8833_DIR)
            TIM3->CCR4 = (499 - i);
        else
            TIM3->CCR4 = (i);

        RTC_GetLocalTime(&dateTime);

        u8g2_ClearBuffer(u8g2);

        sprintf(str, "eeprom %s", at24s ? "errorr" : "ok");
        u8g2_DrawUTF8(u8g2, 5, 10, str);

        sprintf(str, "w25q id = 0x%X", w25qId);
        u8g2_DrawUTF8(u8g2, 5, 23, str);

        sprintf(str, "EN=%d,DIR=%d,i=%03d", (uint8_t)DRV8833_STBY, (uint8_t)DRV8833_DIR, i);
        u8g2_DrawUTF8(u8g2, 5, 36, str);

        sprintf(str, "%02d-%02d-%02d %02d:%02d:%02d", dateTime.year, dateTime.mon, dateTime.day, dateTime.hour, dateTime.min, dateTime.sec);
        u8g2_DrawUTF8(u8g2, 5, 49, str);

        u8g2_SendBuffer(u8g2);

        keyStatus = key_get_status();
        switch(keyStatus) {
            case WKUP_DOWN:
                DRV8833_STBY = !DRV8833_STBY;
                break;
            case WKUP_UP:
                break;
            case EC11_DOWN:
                DRV8833_DIR = !DRV8833_DIR;
                break;
            case EC11_UP:
                break;
            case EC11_S_UP:
                i++;
                break;
            case EC11_S_DOWN:
                i--;
                break;
            default:
                OSTimeDlyHMSM(0, 0, 0, 10, OS_OPT_TIME_HMSM_STRICT, &os_err);
                break;
        }
    }
}
